package cn.b504.qpcr.utils;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import sun.misc.BASE64Encoder;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

public class FileUtils {

  /**
   * 下载文件时，针对不同浏览器，进行附件名的编码
   *
   * @param filename 下载文件名
   * @param agent    客户端浏览器
   * @return 编码后的下载附件名
   */
  public static String encodeDownloadFilename(String filename, String agent) throws IOException {
    if (agent.contains("Firefox")) { // 火狐浏览器
      filename = "=?UTF-8?B?"
          + new BASE64Encoder().encode(filename.getBytes(StandardCharsets.UTF_8))
          + "?=";
      filename = filename.replaceAll("\r\n", "");
    } else { // IE及其他浏览器
      filename = URLEncoder.encode(filename, "utf-8");
      filename = filename.replace("+", " ");
    }
    return filename;
  }

  public static void outputFileWithDate(HttpServletResponse response, String data, String title, String suffix) {
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh_mm_ss");
    String date = format.format(new Date());
    outputFile(response, data, (title + " " + date).trim(), suffix);
  }

  public static void outputFile(HttpServletResponse response, String data, String prefix, String suffix) {
    String fileName = (prefix + suffix).trim();

    response.setContentType("text/plain");
    response.addHeader("Content-Disposition", "attachment;filename=" + fileName);

    try {
      ServletOutputStream outputStream = response.getOutputStream();
      outputStream.write(data.getBytes(StandardCharsets.UTF_8));

      outputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static String outputFileWithDate(String data, String dirName, String suffix) {
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh_mm_ss");
    String date = format.format(new Date());
    return outputFile(data, dirName, date, suffix);
  }

  public static String outputFileWithDate(String data, String dirName, String suffix, boolean isCheckExists) {
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh_mm_ss");
    String date = format.format(new Date());
    return outputFile(data, dirName, date, suffix, isCheckExists);
  }

  public static String outputFile(String data, String dirName, String fileName, String suffix, boolean isCheckExists) {
    String separator = File.separator;

    String path = "C:" + separator + "CqMANs" + separator + dirName;
    if (!existDirectory(path)) {
      return "";
    }

    path += separator + fileName + suffix;

    File file = new File(path);
    if (isCheckExists && file.exists()) {
      return "";
    }

    outputFile(path, data);
    return path;
  }

  public static String outputFile(String data, String dirName, String fileName, String suffix) {
    String separator = File.separator;

    String path = "C:" + separator + "CqMANs" + separator + dirName;
    if (!existDirectory(path)) {
      return "";
    }

    path += separator + fileName + suffix;
    outputFile(path, data);
    return path;
  }

  public static String outputFileWithAbsolutePath(String data, String absolutePath, String fileName, String suffix) {
    String separator = File.separator;

    if (!existDirectory(absolutePath)) {
      return "";
    }

    String path = absolutePath + separator + fileName + suffix;
    outputFile(path, data);
    return path;
  }

  // 输出文件核心方法
  private static void outputFile(String path, String data) {
    OutputStream os = null;
    try {
      os = new FileOutputStream(path);
      os.write(data.getBytes(StandardCharsets.UTF_8));

      os.close();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (os != null) {
        try {
          os.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   * 利用 FileOutputStream 放入固定目录的指定文件夹下
   *
   * @param workbook 要保存的 Excel 文件
   * @param dirName  在固定目录下的这个文件夹内存放
   * @param fileName 文件名
   * @return 保存文件的绝对路径名
   */
  public static String outputExcel(XSSFWorkbook workbook, String dirName, String fileName) {
    String separator = File.separator;

    if (!existDirectory("C:" + separator + "CqMANs" + separator + dirName)) {
      return "";
    }

    String path = "C:" + separator + "CqMANs" + separator + dirName + separator + fileName + ".xlsx";
    FileOutputStream outputStream = null;
    try {
      outputStream = new FileOutputStream(path);
      workbook.write(outputStream);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (outputStream != null) {
        try {
          outputStream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return path;
  }

  /**
   * 利用 FileOutputStream 放入固定目录的根目录下
   *
   * @param workbook 要保存的 Excel 文件
   * @return 保存文件的绝对路径名
   */
  public static String outputExcelWithDate(XSSFWorkbook workbook, String dirName) {
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh_mm_ss");
    String date = format.format(new Date());
    return outputExcel(workbook, dirName, date);
  }

  /**
   * 利用 FileOutputStream 放入固定目录的根目录下
   *
   * @param workbook 要保存的 Excel 文件
   * @return 保存文件的绝对路径名
   */
  public static String outputExcelWithDate(XSSFWorkbook workbook) {
    return outputExcelWithDate(workbook, "");
  }

  /**
   * ServletOutputStream 输出 Excel 文件
   *
   * @param response HttpServletResponse
   * @param workbook 要输出的 XSSFWorkbook 对象
   * @param fileName 输出的文件名
   */
  public static void outputExcel(HttpServletResponse response, XSSFWorkbook workbook, String fileName) {
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.addHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

    try {
      ServletOutputStream outputStream = response.getOutputStream();
      workbook.write(outputStream);

      outputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  /**
   * ServletOutputStream 输出 Excel 文件
   *
   * @param response HttpServletResponse
   * @param workbook 要输出的 XSSFWorkbook 对象
   * @param fileName 输出的文件名
   */
  public static void outputExcelWithDate(HttpServletResponse response, XSSFWorkbook workbook, String fileName) {
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh_mm_ss");
    String date = format.format(new Date());
    outputExcel(response, workbook, (fileName + " " + date).trim());
  }

  /**
   * ServletOutputStream 输出 Excel 文件
   *
   * @param response HttpServletResponse
   * @param workbook 要输出的 XSSFWorkbook 对象
   */
  public static void outputExcelWithDate(HttpServletResponse response, XSSFWorkbook workbook) {
    outputExcelWithDate(response, workbook, "");
  }

  /**
   * ServletOutputStream 输出随机文件名的 Excel 文件
   *
   * @param response HttpServletResponse
   * @param workbook 要输出的 XSSFWorkbook 对象
   */
  public static void outputExcel(HttpServletResponse response, XSSFWorkbook workbook) {
    outputExcel(response, workbook, UUID.randomUUID().toString().replaceAll("-", ""));
  }

  // 判断文件夹是否存在
  private static boolean existDirectory(String fileStr) {
    File file = new File(fileStr);
    return (file.exists() || file.mkdirs()) && file.isDirectory();
  }

  public static void deleteFile(File file) {
    if (file.exists() && file.isFile()) {
      if (!file.delete()) {
        System.err.println("File delete fail: " + file.getAbsolutePath());
        file.deleteOnExit();
      }
    }
  }

  public static void deleteFile(String path) {
    deleteFile(new File(path));
  }
}
